/* ==================================================================   
 * Created [2009-4-27 下午11:32:55] by Jon.King 
 * ==================================================================  
 * TSS 
 * ================================================================== 
 * mailTo:jinpujun@hotmail.com
 * Copyright (c) Jon.King, 2009-2012 
 * ================================================================== 
 */

package com.jinhe.tss.core.cachepool;

import com.jinhe.tss.core.cachepool.strategy.CacheStrategy;
import com.jinhe.tss.core.exception.BusinessException;
import com.jinhe.tss.core.util.BeanUtil;


/** 
 * <p> ObjectPoolListener.java </p> 
 * 
 * @author Jon.King 2007-1-4
 */
public class ObjectPoolListener implements IPoolListener {

    public void dealwithPoolEvent(ObjectPoolEvent poolEvent) {
        IPool pool = poolEvent.getPool();
        if(pool != null){
            switch(poolEvent.getType()){
            case ObjectPoolEvent.CHECKOUT:
            case ObjectPoolEvent.REMOVE:
                // 移除或者检出缓存项时的事件处理
                break;
            case ObjectPoolEvent.CHECKIN:
            case ObjectPoolEvent.PUT_IN:
                synchronized(pool){
                    //唤醒pool对象休息室中可能休眠中的线程，包括cleaner线程（池为空的时候会休眠），checkout，remove等操作的等待线程
                    pool.notifyAll(); 
                }
                checkPoolLimit(pool);
                break;
            case ObjectPoolEvent.MAX_POOL_LIMIT_EXCEEDED:
                pool.getArithmetic().destroy(pool.remove()); // 如果缓存池容量已超过极限，则启动移除销毁
                break;
            case ObjectPoolEvent.MAX_POOL_LIMIT_REACHED:
                pool.purge(); // 如果缓存池容量已经到达极限，则启动缓存清理
                break;
            case ObjectPoolEvent.POOL_RELEASED:
                break;
            case ObjectPoolEvent.STRATEGY_CHANGED_NORMAL:
                changeStrategyNormally(pool);    
                break;
            case ObjectPoolEvent.STRATEGY_CHANGED_INITNUM_RISE:
                // 如果pool.getSize() <  pool.getCacheStrategy().getInitNum()
                // 则补足不足的项,只对ObjectPool类型有效。
                break;
            case ObjectPoolEvent.STRATEGY_CHANGED_SIZE_REDUCE:
                checkPoolLimit(pool);    
                break;
            case ObjectPoolEvent.STRATEGY_CHANGED_RESET:
                resetPool(pool);    
                break;
            default:
                throw new BusinessException("ObjectPoolEvent的type值错误，不存在该类型的事件！");
            }
        }
    }
    
    private void resetPool(IPool pool) {
        pool.release(false);
        pool.init();
    }

    private void checkPoolLimit(IPool pool){
        int maxSize = pool.getCacheStrategy().getPoolSize().intValue();
        //如果maxSize = 0则表示不限制池大小
        if(maxSize > 0 ){
            if(pool.getSize() == maxSize)
                pool.firePoolEvent(ObjectPoolEvent.MAX_POOL_LIMIT_REACHED);
            if(pool.getSize() > maxSize)
                pool.firePoolEvent(ObjectPoolEvent.MAX_POOL_LIMIT_EXCEEDED);
        }
    }
    
    private void changeStrategyNormally(IPool pool){
        CacheStrategy c = pool.getCacheStrategy();
        // 更新池中所有缓存项的生命周期
        for(CacheableKey key : pool.listKeys()){
            Cacheable item = (Cacheable) pool.getOldObject(key);
            if(item == null) continue;
            
            item.setCyclelife(c.getCyclelife().longValue());
        }
        //重新设置缓存池的算法器和缓存项载入器
        pool.setArithmetic((IArithmetic) BeanUtil.newInstanceByName(c.getArithmeticClass()));
        pool.setLoader((ICacheLoader) BeanUtil.newInstanceByName(c.getCacheLoaderClass()));
        
        //因为pool对象都是用Proxy代理的，无法判断到底是ObjectPool，还是SimplePool或其他，
        //调用里面的方法只能通过接口。所以如果需要调用IPool的实现类特有的方法，就必须为该方法单独定义接口。类似ICleaner
        if(pool instanceof ICleaner){
            ((ICleaner)pool).initCleaner(); //重新初始化清除器
        }
    }
    
    /* 
     * 只要是ObjectPoolListener的实例，都返回true
     * @see java.lang.Object#equals(java.lang.Object)
     */
    public boolean equals(Object o){
        if(o instanceof ObjectPoolListener){
            return this.getClass().getName().equals(o.getClass().getName());
        }
        return false;
    }
    
    /* 
     * 所有的ObjectPoolListener实例返回相同的hashCode
     * @see java.lang.Object#hashCode()
     */
    public int hashCode(){
        return 123456789;
    }
}

